<!--
 * @Author: sbotlp
 * @Email: sbotlp@sina.com
 * @Date: 2019-11-18 22:59:33
 * @LastEditTime: 2019-11-20 22:51:06
 * @Description: http://www.sbotlp.com.cn
 -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  diff test
  代码并不能运行，只是大概实现了最基本的diff算法逻辑
  <script>
    var vndeo = {
      tag: 'ul',
      attrs: { id: 'list' },
      children: [
        {
          tag: 'li',
          attrs: { className: 'item' },
          children: ['item1']
        },
        {
          tag: 'li',
          attrs: { className: 'item' },
          children: ['item2']
        }
      ]
    };
    // 把vnode转换成真实DOM
    function createElement(vndeo) {
      const tag = vndeo.tag;
      const attrs = vndeo.attrs || {};
      const children = vndeo.children || [];
      if (!tag) {
        return null;
      }
      // 创建真实的dom元素
      const elem = document.createElement(tag);
      // 属性
      let attrName;
      for (attrName in attrs) {
        // 使用 for in 必须要 使用 hasOwnProperty 方法判断是否为是本身，并非原型中的
        if (attrs.hasOwnProperty(attrName)) {
          // 给elem添加属性
          elem.setAttribute(attrName, attrs[attrName])
        }
      }
      // 子元素
      children.forEach(childrenVnode => {
        // 递归调用 createElement， 给elem添加子元素
        const newElem = createElement(childrenVnode);
        if (newElem) {
          elem.appendChild(newElem);
        }
      });
      // 返回真实dom
      return elem;
    };
    console.log('createElement(vndeo): ', createElement(vndeo));
    // path(vnode, newVode), 当前虚拟dom和新的虚拟dom对比替换，基本逻辑
    function updateChildren(vndeo,newVnode) {
      const children = vndeo.children || [];
      const newChildren = newVnode.children || [];
      children.forEach((childrenVnode, index) => {
        const newChildrenVnode = newChildren[index];
        if (childrenVnode.tag === newChildrenVnode.tag) {
          // 深层次对比，递归
          updateChildren(childrenVnode,newChildrenVnode);
        } else {
          // 替换当前vnode，同 xxxx.replace('xx','cc')
          replaceNode(childrenVnode,newChildrenVnode);
        }
      })
    };
    function replaceNode(vndeo,newVnode) {
      const elem = vndeo.elem // 真实dom节点
      const newElem = createElement(newVnode);
      // 两个都是真实dom之后，
      // 执行替换
      // ........
    };
    /* 
      不仅仅是以上内容
      - 节点新增和删除
      - 节点重新排序
      - 节点属性，样式，事件绑定
      - 如何极致压榨性能
      - 。。。。
    */
  </script>
</body>

</html>